<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      const obj = new Proxy(
        {},
        {
          get: (target, propKey, receiver) => {
            console.log(`getting ${propKey}`);
            return Reflect.get(target, propKey, receiver);
          },
          set: (target, propKey, value, receiver) => {
            console.log(`setting ${propKey} to ${value}`);
            return Reflect.set(target, propKey, value, receiver);
          },
        },
      );
      obj.count = 1;
      ++obj.count;
      const copyObj = Object.create(obj);
      copyObj.count = 3;
      console.log(copyObj, obj);
      // 实现数组负数索引
      const createArray = (...elements) => {
        const handler = {
          get: function (target, propKey, receiver) {
            let index = Number(propKey);
            if (index < 0) {
              propKey = target.length + index;
            }
            return Reflect.get(target, propKey, receiver);
          },
        };
        let target = [];
        target.push(...elements);
        return new Proxy(target, handler);
      };
      let arr = createArray('a', 'b', 'c');
      console.log(arr[-1]);
      // 实现createProxy方法，使计算结果能够满足以下预期
      const createProxy = () => {
        let initialSum = 0;
        const obj = { sum: initialSum };
        const handler = {
          get: function (target, prop, receiver) {
            // 当最后需要将对象转换成number才能跟其他的数相加
            if (prop === Symbol.toPrimitive) {
              return function (hint) {
                return target.sum;
              };
            }
            const num = Number(prop);
            if (!isNaN(num)) {
              return new Proxy({ sum: target.sum + num }, handler);
            }
            return Reflect.get(target, prop, receiver);
          },
        };
        return new Proxy(obj, handler);
      };
      const add = createProxy();
      // console.log(add['sum'], 'add')
      console.log(add[1][2]);
      /* 对比一下Object.defineProperty 和Proxy */
      // 监听对象属性
      const defineReactive = (obj, key, value) => {
        observe(value);
        Object.defineProperty(obj, key, {
          get() {
            console.log('获取：' + key);
            return value;
          },
          set(val) {
            // 如果设置的是对象的话，需要递归增加监听器
            observe(val);
            console.log(key + '-数据改变了');
            value = val;
          },
        });
      };
      const observe = (obj) => {
        if (typeof obj === 'object') {
          for (let key in obj) {
            if (obj.hasOwnProperty(key)) {
              defineReactive(obj, key, obj[key]);
            }
          }
        }
      };
      const dobj = {
        name: '小明',
        flag: {
          book: {
            name: 'js',
            page: 123,
          },
          foods: ['火锅', '旅游'],
        },
      };
      observe(dobj);
      const name = dobj.name;
      dobj.flag.book.name = 'Javascript 从入门到放弃';
      dobj.gender = '男';
      dobj.flag.foods.push('工作');
      console.log(dobj);
    </script>
  </body>
</html>
